﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WowParserLib.Events;
using WowParserLib.EventParsers;
using System.Text.RegularExpressions;

namespace WowParserLib.EventParsers
{
    public class EventParser<T>
        where T : Event, new()//: IEventParser<T>
    {
        private IEventIdProvider _eventIdProvider;

        public EventParser(IEventIdProvider eventIdProvider)
        {
            _eventIdProvider = eventIdProvider;
        }
        /// <summary>
        /// Parses out the timestamp from the log line
        /// </summary>
        /// <param name="line"></param>
        /// <returns></returns>
        private DateTime GetTimestamp(string line, out int timestampSplit)
        {
            timestampSplit = line.IndexOf("  ");
            string date = line.Substring(0, timestampSplit);
            // 3/25 20:12:15.000
            Regex dateTimeRegx = new Regex(@"(\d{1,2})/(\d{1,2})\s(\d{1,2}):(\d{1,2}):(\d{1,2}).(\d{3})");
            Match m = dateTimeRegx.Match(date);
            int month = int.Parse(m.Groups[1].Value);
            int day = int.Parse(m.Groups[2].Value);
            int hour = int.Parse(m.Groups[3].Value);
            int min = int.Parse(m.Groups[4].Value);
            int sec = int.Parse(m.Groups[5].Value);
            int ms = int.Parse(m.Groups[6].Value);

            //line = line.Substring(timestampSplit, line.Length - timestampSplit);

            return new DateTime(DateTime.Now.Year, month, day, hour, min, sec, ms);
        }

        private Reaction GetReaction(int code)
        {
            return (Reaction)(code & (int)Reaction.Mask);
        }

        private Affiliation GetAffiliation(int code)
        {
            return (Affiliation)(code & (int)Affiliation.Mask);
        }
        private Ownership GetOwnership(int code)
        {
            return (Ownership)(code & (int)Ownership.Mask);
        }
        private UnitType GetUnitType(int code)
        {
            return (UnitType)(code & (int)UnitType.Mask);
        }

        #region IEventParser<T> Members
        public T Parse(string eventLine, Actor source, Actor target)
        {
            return Parse(eventLine, source, target, new IArgsParser[0]);
        }

        public T Parse(string eventLine, Actor source, Actor target, IArgsParser[] argumentParsers)
        {
            int timestampLength;
            DateTime timestamp = GetTimestamp(eventLine, out timestampLength);
            string rawDataLine = eventLine.Substring(timestampLength, eventLine.Length - timestampLength).Trim();

            string[] data = rawDataLine.Split(',');
            List<EventArguments> eventArgs = new List<EventArguments>();
            foreach (IArgsParser p in argumentParsers)
            {
                eventArgs.Add(p.Parse(data));
            }
            int sourceFlags = Convert.ToInt32(data[3], 16);
            Affiliation affiliation = GetAffiliation(sourceFlags);
            Reaction reaction = GetReaction(sourceFlags);
            Ownership ownership = GetOwnership(sourceFlags);
            UnitType unitType = GetUnitType(sourceFlags);

            T instance = new T() {
                Affiliation = affiliation, 
                Reaction = reaction, 
                Ownership = ownership, 
                UnitType = unitType 
            };
            //TODO: replace with parameter initialization
            instance.Initialize(_eventIdProvider.GetEventId(), timestamp, source, target, eventArgs.ToArray());
            return instance;

            //return ParseEvent(rawDataLine.Split(','), source, target, timestamp);
        }

        #endregion

    }
}
